<canvas id='canvas' width='800' height='700' />
<script>

    function Point(x, y) {
        this.x = x
        this.y = y
    }
    
    function Line(p1, p2) {
        this.p1 = p1
        this.p2 = p2
        this.length = Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2))
    }

    function Shape() {
        this.points = []
        this.lines = []
        this.init()
    }
    Shape.prototype = {
        constructor: Shape,
        init() {
            if (!this.context) {
                Shape.prototype.context = document.getElementById('canvas').getContext('2d')
            }
        },
        draw() {
            let ctx = this.context
            ctx.beginPath()
            ctx.strokeStyle = this.getColor()
            ctx.moveTo(this.points[0].x, this.points[0].y)
            for (let i = 1; i < this.points.length; i++) {
                ctx.lineTo(this.points[i].x, this.points[i].y)
            }
            ctx.closePath()
            ctx.stroke()
        },
        getArea() {},
        getPerimeter() {
            let lines = this.getLines(), perim = 0
            for (let i = 0; i < lines.length; i++) {
                perim += lines[i].length
            }
            return perim
        },
        getLines() {
            if (!this.lines.length) {
                for (let i = 0; i < this.points.length; i++) {
                    this.lines.push(new Line(this.points[i], this.points[i + 1] || this.points[0]))
                }
            }
            return this.lines
        },
        getColor() {
            let rgb = []
            for (let i = 0; i < 3; i++) {
                rgb.push(Math.round(Math.random() * 255))
            }
            return 'rgb(' + rgb.join(',') + ')'
        }
    }

    function Triangle(p1, p2, p3) {
        this.points = [ p1, p2, p3 ]
        this.getArea = () => {
            let p = this.getPerimeter(), s = p / 2
            return Math.sqrt(s * (s - this.lines[0].length) * (s - this.lines[1].length) * (s - this.lines[2].length))
        }
    }

    function Rectangle(p, sideA, sideB) {
        this.points = [
            p,
            new Point(p.x + sideA, p.y),
            new Point(p.x + sideA, p.y + sideB),
            new Point(p.x, p.y + sideB)
        ]
        this.getArea = () => {
            return sideA * sideB
        }
    }

    function Square(p, side) {
        Rectangle.call(this, p, side, side)
    }

    (() => {
        Triangle.prototype = Rectangle.prototype =  Square.prototype = new Shape()
    })()

    let t1 = new Triangle(new Point(100, 100), new Point(400, 200), new Point(300, 300)),
        t2 = new Triangle(new Point(150, 150), new Point(450, 250), new Point(350, 350)),
        t3 = new Triangle(new Point(50, 50), new Point(350, 150), new Point(250, 250)),
        r1 = new Rectangle(new Point(200, 300), 300, 200),
        r2 = new Rectangle(new Point(250, 350), 350, 250),
        r3 = new Rectangle(new Point(150, 250), 250, 150),
        s1 = new Square(new Point(300, 200), 400),
        s2 = new Square(new Point(350, 250), 450),
        s3 = new Square(new Point(250, 150), 350)

        t1.draw()
        r1.draw()
        s1.draw()
        t2.draw()
        r2.draw()
        s2.draw()
        t3.draw()
        r3.draw()
        s3.draw()
</script>